home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / editors / mntemacs.zoo / src / insdel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-02  |  8.5 KB  |  379 lines

  1. /* Buffer insertion/deletion and gap motion for GNU Emacs.
  2.    Copyright (C) 1985, 1986, 1990 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include "config.h"
  22. #include "lisp.h"
  23. #include "buffer.h"
  24. #include "window.h"
  25.  
  26. /* Move gap to position `pos'.
  27.    Note that this can quit!  */
  28.  
  29. move_gap (pos)
  30.      int pos;
  31. {
  32.   if (pos < GPT)
  33.     gap_left (pos, 0);
  34.   else if (pos > GPT)
  35.     gap_right (pos);
  36. }
  37.  
  38. /* Move the gap to POS, which is less than the current GPT.
  39.    If NEWGAP is nonzero, then don't update beg_unchanged and end_unchanged.  */
  40.  
  41. gap_left (pos, newgap)
  42.      register int pos;
  43.      int newgap;
  44. {
  45.   register unsigned char *to, *from;
  46.   register int i;
  47.   int new_s1;
  48.  
  49.   pos--;
  50.  
  51.   if (!newgap)
  52.     {
  53.       if (unchanged_modified == MODIFF)
  54.     {
  55.       beg_unchanged = pos;
  56.       end_unchanged = Z - pos - 1;
  57.     }
  58.       else
  59.     {
  60.       if (Z - GPT < end_unchanged)
  61.         end_unchanged = Z - GPT;
  62.       if (pos < beg_unchanged)
  63.         beg_unchanged = pos;
  64.     }
  65.     }
  66.  
  67.   i = GPT;
  68.   to = GAP_END_ADDR;
  69.   from = GPT_ADDR;
  70.   new_s1 = GPT - BEG;
  71.  
  72.   /* Now copy the characters.  To move the gap down,
  73.      copy characters up.  */
  74.  
  75.   while (1)
  76.     {
  77.       /* I gets number of characters left to copy.  */
  78.       i = new_s1 - pos;
  79.       if (i == 0)
  80.     break;
  81.       /* If a quit is requested, stop copying now.
  82.      Change POS to be where we have actually moved the gap to.  */
  83.       if (QUITP)
  84.     {
  85.       pos = new_s1;
  86.       break;
  87.     }
  88.       /* Move at most 32000 chars before checking again for a quit.  */
  89.       if (i > 32000)
  90.     i = 32000;
  91.       new_s1 -= i;
  92.       while (--i >= 0)
  93.     *--to = *--from;
  94.     }
  95.  
  96.   /* Adjust markers, and buffer data structure, to put the gap at POS.
  97.      POS is where the loop above stopped, which may be what was specified
  98.      or may be where a quit was detected.  */
  99.   adjust_markers (pos + 1, GPT, GAP_SIZE);
  100.   GPT = pos + 1;
  101.   QUIT;
  102. }
  103.  
  104. gap_right (pos)
  105.      register int pos;
  106. {
  107.   register unsigned char *to, *from;
  108.   register int i;
  109.   int new_s1;
  110.  
  111.   pos--;
  112.  
  113.   if (unchanged_modified == MODIFF)
  114.     {
  115.       beg_unchanged = pos;
  116.       end_unchanged = Z - pos - 1;
  117.     }
  118.   else
  119.     {
  120.       if (Z - pos - 1 < end_unchanged)
  121.     end_unchanged = Z - pos - 1;
  122.       if (GPT - BEG < beg_unchanged)
  123.     beg_unchanged = GPT - BEG;
  124.     }
  125.  
  126.   i = GPT;
  127.   from = GAP_END_ADDR;
  128.   to = GPT_ADDR;
  129.   new_s1 = GPT - 1;
  130.  
  131.   /* Now copy the characters.  To move the gap up,
  132.      copy characters down.  */
  133.  
  134.   while (1)
  135.     {
  136.       /* I gets number of characters left to copy.  */
  137.       i = pos - new_s1;
  138.       if (i == 0)
  139.     break;
  140.       /* If a quit is requested, stop copying now.
  141.      Change POS to be where we have actually moved the gap to.  */
  142.       if (QUITP)
  143.     {
  144.       pos = new_s1;
  145.       break;
  146.     }
  147.       /* Move at most 32000 chars before checking again for a quit.  */
  148.       if (i > 32000)
  149.     i = 32000;
  150.       new_s1 += i;
  151.       while (--i >= 0)
  152.     *to++ = *from++;
  153.     }
  154.  
  155.   adjust_markers (GPT + GAP_SIZE, pos + 1 + GAP_SIZE, - GAP_SIZE);
  156.   GPT = pos + 1;
  157.   QUIT;
  158. }
  159.  
  160. /* Add `amount' to the position of every marker in the current buffer
  161.    whose current position is between `from' (exclusive) and `to' (inclusive).
  162.    Also, any markers past the outside of that interval, in the direction
  163.    of adjustment, are first moved back to the near end of the interval
  164.    and then adjusted by `amount'.  */
  165.  
  166. adjust_markers (from, to, amount)
  167.      register int from, to, amount;
  168. {
  169.   Lisp_Object marker;
  170.   register struct Lisp_Marker *m;
  171.   register int mpos;
  172.  
  173.   marker = current_buffer->markers;
  174.  
  175.   while (!NULL (marker))
  176.     {
  177.       m = XMARKER (marker);
  178.       mpos = m->bufpos;
  179.       if (amount > 0)
  180.     {
  181.       if (mpos > to && mpos < to + amount)
  182.         mpos = to + amount;
  183.     }
  184.       else
  185.     {
  186.       if (mpos > from + amount && mpos <= from)
  187.         mpos = from + amount;
  188.     }
  189.       if (mpos > from && mpos <= to)
  190.     mpos += amount;
  191.       m->bufpos = mpos;
  192.       marker = m->chain;
  193.     }
  194. }
  195.  
  196. /* Make the gap INCREMENT characters longer.  */
  197.  
  198. make_gap (increment)
  199.      int increment;
  200. {
  201.   unsigned char *memory;
  202.   Lisp_Object tem;
  203.   int real_gap_loc;
  204.   int old_gap_size;
  205.  
  206.   /* If we have to get more space, get enough to last a while.  */
  207.   increment += 2000;
  208.  
  209.   memory = (unsigned char *) realloc (BEG_ADDR,
  210.                       Z - BEG + GAP_SIZE + increment);
  211.   if (memory == 0)
  212.     memory_full ();
  213.   BEG_ADDR = memory;
  214.  
  215.   /* Prevent quitting in move_gap.  */
  216.   tem = Vinhibit_quit;
  217.   Vinhibit_quit = Qt;
  218.  
  219.   real_gap_loc = GPT;
  220.   old_gap_size = GAP_SIZE;
  221.   /* Call the newly allocated space a gap at the end of the whole space.  */
  222.   GPT = Z + GAP_SIZE;
  223.   GAP_SIZE = increment;
  224.   /* Move the new gap down to be consecutive with the end of the old one.
  225.      This adjusts the markers properly too.  */
  226.   gap_left (real_gap_loc + old_gap_size, 1);
  227.   /* Now combine the two into one large gap.  */
  228.   GAP_SIZE += old_gap_size;
  229.   GPT = real_gap_loc;
  230.  
  231.   Vinhibit_quit = tem;
  232. }
  233.  
  234. /* Insert the character c before point */
  235.  
  236. insert_char (c)
  237.      unsigned char c;
  238. {
  239.   insert (&c, 1);
  240. }
  241.  
  242. /* Insert the null-terminated string s before point */
  243.  
  244. InsStr (s)
  245.      char *s;
  246. {
  247.   insert (s, strlen (s));
  248. }
  249.  
  250. /* Insert a string of specified length before point */
  251.  
  252. insert (string, length)
  253.      register unsigned char *string;
  254.      register length;
  255. {
  256.   register Lisp_Object temp;
  257.  
  258.   if (length < 1)
  259.     return;
  260.  
  261.   /* Make sure point-max won't overflow after this insertion.  */
  262.   XSET (temp, Lisp_Int, length + Z);
  263.   if (length + Z != XINT (temp))
  264.     error ("maximum buffer size exceeded");
  265.  
  266.   prepare_to_modify_buffer ();
  267.  
  268.   if (point != GPT)
  269.     move_gap (point);
  270.   if (GAP_SIZE < length)
  271.     make_gap (length - GAP_SIZE);
  272.  
  273.   record_insert (point, length);
  274.   MODIFF++;
  275.  
  276.   bcopy (string, GPT_ADDR, length);
  277.  
  278.   GAP_SIZE -= length;
  279.   GPT += length;
  280.   ZV += length;
  281.   Z += length;
  282.   point += length;
  283. }
  284.  
  285. /* like insert except that all markers pointing at the place where
  286.    the insertion happens are adjusted to point after it.  */
  287.  
  288. insert_before_markers (string, length)
  289.      unsigned char *string;
  290.      register int length;
  291. {
  292.   register int opoint = point;
  293.   insert (string, length);
  294.   adjust_markers (opoint - 1, opoint, length);
  295. }
  296.  
  297. /* Delete characters in current buffer
  298.   from `from' up to (but not incl) `to' */
  299.  
  300. del_range (from, to)
  301.      register int from, to;
  302. {
  303.   register int numdel;
  304.  
  305.   /* Make args be valid */
  306.   if (from < BEGV)
  307.     from = BEGV;
  308.   if (to > ZV)
  309.     to = ZV;
  310.  
  311.   if ((numdel = to - from) <= 0)
  312.     return;
  313.  
  314.   /* Make sure the gap is somewhere in or next to what we are deleting */
  315.   if (from > GPT)
  316.     gap_right (from);
  317.   if (to < GPT)
  318.     gap_left (to, 0);
  319.  
  320.   prepare_to_modify_buffer ();
  321.   record_delete (from, numdel);
  322.   MODIFF++;
  323.  
  324.   /* Relocate point as if it were a marker.  */
  325.   if (from < point)
  326.     {
  327.       if (point < to)
  328.     point = from;
  329.       else
  330.     point -= numdel;
  331.     }
  332.  
  333.   /* Relocate all markers pointing into the new, larger gap
  334.      to point at the end of the text before the gap.  */
  335.   adjust_markers (to + GAP_SIZE, to + GAP_SIZE, - numdel - GAP_SIZE);
  336.  
  337.   GAP_SIZE += numdel;
  338.   ZV -= numdel;
  339.   Z -= numdel;
  340.   GPT = from;
  341.  
  342.   if (GPT - BEG < beg_unchanged)
  343.     beg_unchanged = GPT - BEG;
  344.   if (Z - GPT < end_unchanged)
  345.     end_unchanged = Z - GPT;
  346. }
  347.  
  348. modify_region (start, end)
  349.      int start, end;
  350. {
  351.   prepare_to_modify_buffer ();
  352.   if (start - 1 < beg_unchanged || unchanged_modified == MODIFF)
  353.     beg_unchanged = start - 1;
  354.   if (Z - end < end_unchanged
  355.       || unchanged_modified == MODIFF)
  356.     end_unchanged = Z - end;
  357.   MODIFF++;
  358. }
  359.  
  360. prepare_to_modify_buffer ()
  361. {
  362.   if (!NULL (current_buffer->read_only))
  363.     Fbarf_if_buffer_read_only();
  364.  
  365. #ifdef CLASH_DETECTION
  366.   if (!NULL (current_buffer->filename)
  367.       && current_buffer->save_modified >= MODIFF)
  368.     lock_file (current_buffer->filename);
  369. #else
  370.   /* At least warn if this file has changed on disk since it was visited.  */
  371.   if (!NULL (current_buffer->filename)
  372.       && current_buffer->save_modified >= MODIFF
  373.       && NULL (Fverify_visited_file_modtime (Fcurrent_buffer ()))
  374.       && !NULL (Ffile_exists_p (current_buffer->filename)))
  375.     call1 (intern ("ask-user-about-supersession-threat"),
  376.        current_buffer->filename);
  377. #endif /* not CLASH_DETECTION */
  378. }
  379.